#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/time.h>
#include<fcntl.h>

char test_start_address[1024] = "GET /index.html HTTP/1.1\r\nHOST:127.0.0.1\r\n\r\n";
int test_start_size = strlen(test_start_address);

int thread_number = 100;
int port = 8080;
char* ip = NULL;

int test_size = 1024;

const int write_buff_size = 1024;

void * work(void *address)
{
	for(int i  = 0; i< test_size; i++)
	{
		int fd,ret;
		struct sockaddr_in addr = {0};
		struct in_addr x;
		inet_aton(ip,&x);
		addr.sin_family = AF_INET;
		addr.sin_addr = x;
		addr.sin_port = htons(port);
		fd = socket(AF_INET,SOCK_STREAM,0);
		
		int write_count = 0;
		int temp = 0;
		
		char buff[1024] = {'\0'};
		
		if(fd == -1)
		{
			printf("fd error\n");
			return NULL;
		}
		
		ret = connect(fd,(sockaddr*)&addr,sizeof(addr));
		if(ret == -1)
		{
			printf("connect error\n");
			goto error;
		}
		  
		//write test start
		while (1) {
			if (write_count >= test_start_size) {
				printf("break\n");
				break;
			}
			
			//printf("sending %d\n", write_count);
			
			temp = write(fd , test_start_address + write_count,
					test_start_size - write_count);
					
			if (temp <= -1) {
				printf("test error:%d\n", errno);
				goto error;
			}
			
			if (temp == 0) {
				printf("peer closed:%d\n", errno);
				goto error;
			}

			write_count += temp;
			if (write_count >= test_start_size) {
				//printf("test ok\n");
				break;
			}
		}

		temp = 0;
		temp = read(fd, buff, 1024) ;
		//printf("buff:%s\n",buff);
		
		error:
			close(fd);
	}
	
	return NULL;
}

int main(int argc, char *argv[])
{
	if (argc <= 4) {
		printf("usage: %s ip_address port_number thread_number testsize(KB),\n", basename(argv[0]));
		return 1;
	}
	
	ip = argv[1];
	int port = atoi(argv[2]);
	thread_number = atoi(argv[3]);
	test_size = atoi(argv[4]);
	
	struct  timezone   tz;
	struct  timeval    start_time, end_time;
	gettimeofday(&start_time,&tz);
	
	pthread_t *m_threads = new pthread_t[thread_number];
	for (int i = 0; i < thread_number; ++i) {
		
		if (pthread_create(m_threads + i, NULL, work, NULL) != 0) {
			printf("pthread_create error\n");
			delete[] m_threads;
			return -1;
		}
	}
	
	for (int i = 0; i < thread_number; ++i) {
		pthread_join(m_threads[i], NULL);
	}
	
	gettimeofday(&end_time,&tz);

	
	printf("request:%ld\n", thread_number*test_size/(end_time.tv_sec - start_time.tv_sec ));
	
	printf("test all ok\n");
}

